/*
    SlideScript - minimalistic top-down scripting language.
    (C) Copyright 2014-2022 Chris Dorman - some rights reserved (GPLv2)

    View README file supplied with this software for more details
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <strings.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <regex.h>
#include <limits.h>
#include <stddef.h>
#include "config.h"
#include "sbyteswap.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/select.h>
// Networking
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
// For file handling
#include <assert.h>
#include <sys/stat.h>
// For string searching
#include <regex.h>
// Math for compression algorithm
#include <stdint.h>
#include <math.h>

#define MAX_VAR_NAME_LEN  	    512
#define MAX_VAR_NAME_BUFSIZE	(MAX_VAR_NAME_LEN + 1)
#define MAX_STRING_LEN          65535
#define MAX_STRING_BUFSIZE      (MAX_STRING_LEN + 1)
#define MAX_VAR_DATA_LEN 	    65535
#define MAX_DATA_BUFSIZE        (MAX_VAR_DATA_LEN + 1)
#define MAXVARS          	    1488
#define MAX_PIPE_CMDS           32
// for networking functions
#define MAX_ADDRESS_LEN         256
#define MAX_ADDRESS_BUF         (MAX_ADDRESS_LEN + 1)
#define MAX_NETSRCH_LEN         4096
#define MAX_NETSRCH_BUF         (MAX_NETSRCH_LEN + 1)
#define MAX_NETRESP_LEN         65536
#define MAX_NETRESP_BUF         (MAX_NETRESP_BUF + 1)
// For Expr
#define MAX_EXPR_ARGS           128
#define MAX_EXPR_LEN            512
// For search
#define MAX_SEARCH_LEN          65536
#define MAX_SEARCH_BUFSIZE      (MAX_SEARCH_LEN + 1)
// For files
#define MAX_FILENAME_LEN        1024
#define MAXPATHLENGTH           8128
#define MAX_FILENAME_BUFSIZE    (MAX_FILENAME_LEN + 1)
#define MAX_FILES               1024
// Inset backquote buffers
#define MAX_BQ_FUNCTIONS        128
// END
#define TOKEN             	    '%'
#define TOKEN_STR         	    "%"
#define TOKEN_BQ                '`'
#define NULLBYTE                '\0'
#define NEWLINE                 '\n'
#define ENCOFFSET               80
#define ENCSTEPODD              2
#define ENCSTEPEVEN             3

#define PATH                    "/bin:/usr/bin:/usr/local/bin:/freon/bin:/opt"

// HELP PRINTOUT

#define FUNCTION_HELP "-[Main Functions]-\n Need function information? Use: help <function> \n list:\n" \
                      "print, " \
                      "sleep, " \
                      "encode, " \
                      "decode, " \
                      "compress, " \
                      "decompress, " \
                      "calc, " \
                      "move, " \
                      "chdir, " \
                      "showdir, " \
                      "showpath, " \
                      "isdir, " \
                      "isfile, " \
                      "delete, " \
                      "nethttp, " \
                      "read, " \
                      "write, " \
                      "cat, " \
                      "unset \n " \
                      "\n-[Variables, Pipes, and Backquoting]-\nExample:\n" \
                      " FORK=`isfile \"index.html\"` -> returns 1 on find\n" \
                      " write \"port.txt\" \"8888\" -> writes '8888' to port.txt\n" \
                      " read \"port.txt\" | nethttp \"%PIPE%\" \"%FORK%\"\n\n" \
                      "This an example of how piping works, along with variables and \n" \
                      "backquote function execution. Return values are saved as variables.\n" \
                      "\n-[Specials]-\nExample:\n" \
                      "comp: \"<int1/str1>\" \"<int2/str2>\" -> returns (true|false)\n" \
                      "loop: <int>; <function> -> loops function for 'int' times\n" \
                      "if(n): <true/false/1/0>; <function> -> Processes function if true or false\n"

// Purpose:   UX3 basic definitions
// License:   MIT/X. (c) OldCoder (Robert Kiraly) 1987-2022.

#ifndef _X3BASIC_H              /* skip this file if loaded     */
#define _X3BASIC_H 1            /* flag this file               */

/* ------------------------------------------------------------ */
/*                        basic definitions                     */
/* ------------------------------------------------------------ */

#ifndef ZERO
#define ZERO        0
#endif                          // Endif ZERO

#ifndef ONE
#define ONE         1
#endif                          // Endif ONE

#ifndef FALSE
#define FALSE       0
#endif                          // Endif FALSE

#ifndef TRUE
#define TRUE        1
#endif                          // Endif TRUE

#ifndef CH_EOS
#define CH_EOS      '\0'
#endif                          // Endif CH_EOS

#ifndef x3u_char
#define x3u_char    unsigned char
#endif

#ifndef x3u_int
#define x3u_int     unsigned int
#endif

#ifndef x3u_long
#define x3u_long    unsigned long
#endif

#ifndef MODPRIV                 // Module-private
#define MODPRIV     static
#endif                          // Endif MODPRIV

#ifndef MODPUB                  // Module-public
#define MODPUB
#endif                          // Endif MODPUB

#ifndef REG_VAR
#define REG_VAR
#endif                          // Endif NULL_PTR

/* ------------------------------------------------------------ */
/*                 "erase item" macro functions                 */
/* ------------------------------------------------------------ */

/* If "dp" is a  data pointer (of any type) and "nb" is a short */
/* or  long integer,  "b_clr(dp,nb)" clears "nb" bytes to zero, */
/* starting with the first byte pointed to by "dp".             */

/* Note:  "nb" may use any  integer data type, but the value of */
/* "nb" should fit into an unsigned integer.                    */

#define b_clr(dp,nb)                            \
        {                                       \
            REG_VAR char *cp = (char *) (dp);   \
            REG_VAR u_int x  = (u_int)  (nb);   \
            while (x-- > ZERO) *cp++ = CH_EOS;  \
        }

/* ------------------------------------------------------------ */

/* If "a[]" is an array, "a_clr(a)" clears the array (bytewise) */
/* to  zero.  "a[]" must  be an  array and not a  pointer.  The */
/* array must have a known fixed size.                          */

#define a_clr(a)        b_clr ((char *) (&((a)[0])),sizeof(a))

/* ------------------------------------------------------------ */

/* If "p" is a  pointer to a  structure or variable, "p_clr(p)" */
/* clears the structure or  variable.  The pointer object  must */
/* have a known fixed size.                                     */

#define p_clr(p)        b_clr ((char *) (p),sizeof(*p))

/* ------------------------------------------------------------ */

/* If "x" is a  variable (and not an array), "v_clr(x)"  clears */
/* the variable  (bytewise) to zero.  The variable must  have a */
/* known fixed size.                                            */

#define v_clr(x)        b_clr ((char *) (&(x)),sizeof(x))

/* ------------------------------------------------------------ */
/*                    handle "void" data type                   */
/* ------------------------------------------------------------ */

/* The following  five symbols provide a portable  interface to */
/* the  "void"  data type.  These  five symbols are  translated */
/* appropriately for  systems which  don't  support the  "void" */
/* type.                                                        */

/*      (a) V_FUNC      --  defines  a void function            */
/*      (b) V_PROTO     --  declares a void function            */
/*      (c) NO_PARAM    --  void function parameter type        */
/*      (d) V_CAST      --  void typecast                       */
/*      (e) V_OBJ       --  void pointer object                 */

/* ------------------------------------------------------------ */

/* V_FUNC may be used to declare a void function in the follow- */
/* ing context:                                                 */
/*                                                              */
/*      V_FUNC function-definition(...) { ... }                 */

/* V_FUNC  should  not  be  used in  function  declarations  or */
/* function prototypes.                                         */

/* ------------------------------------------------------------ */

/* V_PROTO  may be  used to  declare  a  void function  in  the */
/* following two contexts:                                      */
/*                                                              */
/*      V_PROTO function-declaration();                         */
/*      V_PROTO function-prototype(...);                        */

/* V_PROTO should not be used in function definitions.          */

/* ------------------------------------------------------------ */

/* NO_PARAM  may be  used to  declare a void function argument; */
/* for example,                                                 */
/*                                                              */
/*      int foo(NO_PARAM) { ... }                               */

/* NO_PARAM may be used in  function declarations,  in function */
/* definitions, and in function prototypes.                     */

/* ------------------------------------------------------------ */

/* "V_OBJ *" translates into the appropriate  void-pointer data */
/* type; for example,                                           */
/*                                                              */
/*      V_OBJ *malloc (argp1 (u_int));                          */

/* ------------------------------------------------------------ */

/* V_CAST translates into a "void" typecast; for example,       */
/*                                                              */
/*      char *strcpy (argp2(char *,char *));                    */
/*      V_CAST strcpy (s,t);                                    */

/* ------------------------------------------------------------ */

/* if "void" is not supported   */

#ifdef NO_VOID                  /* "void" type is not supported */
#define NO_PARAM                /* void parameter type (empty)  */
#define V_CAST                  /* void typecast (no effect)    */
#define V_FUNC                  /* void function definition     */
#define V_OBJ       char        /* void pointer object          */
#define V_PROTO     extern      /* void function declaration    */
#endif                          /* endif "void not supported"   */

/* ------------------------------------------------------------ */

/* if "void" is supported       */

#ifndef NO_VOID                 /* "void" type is supported     */
#ifdef NO_PROTO                 /* prototypes are not supported */
#define NO_PARAM                /* void parameter type (empty)  */
#else                           /* prototypes are supported     */
#define NO_PARAM    void        /* void parameter type          */
#endif                          /* endif NO_PARAM               */
#endif                          /* endif "void is supported"    */

#ifndef NO_VOID                 /* "void" type is supported     */
#define V_CAST      (void)      /* void typecast                */
#define V_FUNC      void        /* void function definition     */
#define V_OBJ       void        /* void pointer object          */
#define V_PROTO     void        /* void function declaration    */
#endif                          /* endif "void is supported"    */

/* ------------------------------------------------------------ */
/*                      ANSI prototype setup                    */
/* ------------------------------------------------------------ */

/* The  following  "argp#(...)"  macros  may  be used  in  ANSI */
/* function prototypes.  "#" should be replaced with the number */
/* of function arguments; e.g.:                                 */
/*                                                              */
/*      V_OBJ *malloc (argp1(u_int));                           */
/*      char *strcpy (argp2(char *,char *));                    */

/* The  "argp#(...)" macros  discard their arguments on systems */
/* which do not support ANSI prototypes.                        */

/* The "ellipse" construct "..." counts as one argument.        */

/* ------------------------------------------------------------ */

#ifdef NO_PROTO
#define argp0()
#define argp1(a)
#define argp2(a,b)
#define argp3(a,b,c)
#define argp4(a,b,c,d)
#define argp5(a,b,c,d,e)
#define argp6(a,b,c,d,e,f)
#define argp7(a,b,c,d,e,f,g)
#define argp8(a,b,c,d,e,f,g,h)
#define argp9(a,b,c,d,e,f,g,h,i)
#else
#define argp0()                     NO_PARAM
#define argp1(a)                    a
#define argp2(a,b)                  a,b
#define argp3(a,b,c)                a,b,c
#define argp4(a,b,c,d)              a,b,c,d
#define argp5(a,b,c,d,e)            a,b,c,d,e
#define argp6(a,b,c,d,e,f)          a,b,c,d,e,f
#define argp7(a,b,c,d,e,f,g)        a,b,c,d,e,f,g
#define argp8(a,b,c,d,e,f,g,h)      a,b,c,d,e,f,g,h
#define argp9(a,b,c,d,e,f,g,h,i)    a,b,c,d,e,f,g,h,i
#endif

/* ------------------------------------------------------------ */
/*                null pointers of various types                */
/* ------------------------------------------------------------ */

/* Note: NULLXP is a null function pointer.                     */

#ifndef NULLXP
#define NULL_PTR    ((void  *)   ZERO)
#define NULLCP      ((char  *)   ZERO)
#define NULLFP      ((FILE  *)   ZERO)
#define NULLVP      ((V_OBJ *)   ZERO)
#define NULLXP      ((int (*)()) ZERO)
#endif                          // Endif NULLXP

/* ------------------------------------------------------------ */
/*                   resolve global variables                   */
/* ------------------------------------------------------------ */

#ifdef RES_UX3                  /* resolve external variables?  */
#define UX3_EXT                 /* yes                          */
#else                           /* no                           */
#define UX3_EXT     extern      /* variables are externals      */
#endif

#ifdef VMS                      /* VMS host                     */
#undef UX3_EXT
#ifdef RES_UX3                  /* resolve externals?           */
#define UX3_EXT     globaldef
#else                           /* don't resolve externals      */
#define UX3_EXT     globalref
#endif                          /* endif RES_UX3                */
#endif                          /* endif VMS                    */

/* ------------------------------------------------------------ */
/*                          wrap it up                          */
/* ------------------------------------------------------------ */

#endif                          // Endif _X3BASIC_H
